//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<python_plug.h>
///	@path	~/src/python/
///	@date	2007/05/03
///	@desc	Low level python execution plug.

#pragma once

#include "xeres.h"

#include "database/store/IFileSystem.h"
#include "python/py_boost_decl.h"

namespace xeres
{
	// python internal
	struct _PythonMain;

	/*!
		\class	PythonPlug
		\brief	Low level python execution plug. For python interpreter use only.
	*/
	class PythonPlug
	{
	public:

		/// \instance
		static PythonPlug& instance( void );

	//@ interface

		/*!
			\brief		Initialize global python plug.
		*/
#ifndef _PYXERES
		bool Initialize( const WString& program , const WString& pythonhome , const WString& pythonPaths ,
			RefWeak<IFileSystem> filesystem );
#else
		bool Initialize( RefWeak<IFileSystem> filesystem );
#endif

		/*!
			\brief		Finalize python plug.
		*/
		void Finalize( void );

		/*!
			\brief		Is python initialized.
		*/
		bool IsInitialized( void );

		/*! 
			\brief		Redirect python's stdio(stdout/stderr).
		*/
		void RedirStdio( void );

		/*! 
			\brief		Restore python's stdio(stdout/stderr).
		*/
		void RestoreStdio( void );

		/*! 
			\brief		Enable stdio output.
		*/
		void EnableStdout( bool enable_stdout , bool enable_stderr );

		/*! 
			\brief		Set default encoding type, could be 'utf-8', 'latin-1', 'mbcs', 'ascii'.
		*/
		void SetEncoding( const char * encoding );

		/*!
			\brief		Register module to python.
		*/
		bool RegisterModule( const char * module_name , function<void(void)> module_call );

		/*!
			\brief		Register object to python
		*/
		void RegisterObject( const char * module_name , const char * name , boost::python::object obj );

		/*!
			\brief		Register object to python
		*/
		void RegisterObject( const char * module_name , const char * name , PyObject * obj );

		/*!
			\brief		Find member in python.
		*/
		boost::python::object FindMember( const char * module_name , const char * member_name );

		/*!
			\brief		Run codes in string.
		*/
		bool RunString( const char * string );

		/*!
			\brief		Run codes in file.
		*/
		void RunFile( const char * filename );

		/*!
			\brief		Run expression.
		*/
		boost::python::object RunExpression( const char * expr );

		/*! 
			\brief		Inline a script code.
		*/
		boost::python::object InlineCode( const char * module_name , const char * name , const char * script );

		/*! 
			\brief		Inline a compiled script.
		*/
		boost::python::object InlineCompiled( const char * module_name , boost::python::object co );

		/*!
			\brief		Get python's file system.
		*/
		RefWeak<IFileSystem> GetFilesystem( void ) { return m_filesystem; }

		/*! 
			\brief		Register a cleanup call.
		*/
		void RegisterCleanup( function<void()> call );

	private:

		/// \ctor
		PythonPlug( void );

		/// \dtor
		~PythonPlug( void );

	//@ data

		// file system
		Ref<IFileSystem>		m_filesystem;

		// main module
		_PythonMain *			m_main;

		// uninitialize calls.
		std::vector< function<void()> >		m_cleanUp;
		
		// stdio
		PyObject *				m_stdout;
		PyObject *				m_stderr;
	};

} // namespace xeres
